package com.jerry.api.common;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author Jerry Chan
 * @Email 670809626@qq.com
 * @date 2018年03月30日
 * @descreption 类
 */
public class RandomStrUtils {

    private static final Logger log = LoggerFactory.getLogger(RandomStrUtils.class);
    private static String encodingCharset = "UTF-8";

    // 过期时间：不重复的时间间隔(ms)
    private static final long expireTime = 60*1000;
    private static Object lock = new Object();
    private Map<String, Long> randomStrMap = new ConcurrentHashMap<String, Long>();

    private static final String[] BASE_STRING = new String[]{
            "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
            "a", "b", "c", "d", "e", "f", "g", "h", "i", "j",
            "k", "l", "m", "n", "o", "p", "q", "r", "s", "t",
            "u", "v", "w", "x", "y", "z", "A", "B", "C", "D",
            "E", "F", "G", "H", "I", "J", "K", "L", "M", "N",
            "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"
    };
    private static final int RANDOM_STRING_LENGTH = 6;

    private RandomStrUtils() {
    }

    private static RandomStrUtils instance;
    public static RandomStrUtils getInstance() {
        synchronized (lock) {
            if (instance == null) {
                instance = new RandomStrUtils();
            }
        }
        return instance;
    }

    private String getRandomString() {

        Long nowTime = System.currentTimeMillis();
        String randomStr = null;
        synchronized (lock) {
            // 生成随机字符串
            randomStr = createRandomString(RANDOM_STRING_LENGTH, nowTime);
            // 删除规定时间间隔内重复的随机字符串
            Iterator<Map.Entry<String, Long>> it = randomStrMap.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry<String, Long> entry = it.next();
                Long value = entry.getValue();
                if (nowTime - value > expireTime) {
                    it.remove();
                }
            }
        }

        return randomStr;
    }

    private String createRandomString(int len, Long nowTime) {

        Random random = new Random();
        int length = BASE_STRING.length;
        String randomString = "";
        for (int i = 0; i < length; i++) {
            randomString += BASE_STRING[random.nextInt(length)];
        }

        random = new Random(System.currentTimeMillis());
        String resultStr = "";
        for (int i = 0; i < len; i++) {
            resultStr += randomString.charAt(random.nextInt(randomString.length() - 1));
        }

        // 判断规定时间间隔内是否重复
        Long randomStrCreateTime = randomStrMap.get(resultStr);
        if (randomStrCreateTime != null &&
                nowTime - randomStrCreateTime < expireTime) {
            resultStr = createRandomString(len, nowTime);
        }
        randomStrMap.put(resultStr, nowTime);
        return resultStr;
    }

    public static String toHex(byte input[]) {
        if (input == null) {
            return null;
        }
        StringBuffer output = new StringBuffer(input.length * 2);
        for (int i = 0; i < input.length; i++) {
            int current = input[i] & 0xff;
            if (current < 16) {
                output.append("0");
            }
            output.append(Integer.toString(current, 16));
        }

        return output.toString();
    }

    public static String md5(String value) {
        MessageDigest md = null;
        try {
            byte[] data = value.getBytes(encodingCharset);
            md = MessageDigest.getInstance("MD5");
            byte[] digestData = md.digest(data);
            return toHex(digestData);
        } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static String getRandomStr(){
        RandomStrUtils randomUtil = RandomStrUtils.getInstance();
        String randomStr = randomUtil.getRandomString();
        String md5RandomStr = RandomStrUtils.md5(randomStr);
        return md5RandomStr;
    }

    public static void main(String[] args) {
        String randomStr = RandomStrUtils.getRandomStr();
        System.out.println(randomStr);
    }

}
